<?php
/**
 * Zend Framework Examples
 *
 * @category  Sfs
 * @package   TryIt
 * @author    Michel Corne
 * @copyright 2009 Michel Corne
 * @license   http://www.opensource.org/licenses/bsd-license.php The BSD License
 * @see       http://zend-framework-examples.blogspot.com
*/

/*
In this example, we get or set dates in different timezones.
We display parts of dates and times in various formats.
We also get informations on sunrise and sunset in several locations.
*/

class  Sfs_Date
{

    /* Processing the date and time */
    public function process()
    {
        // We get the locale, the timezone, the date, the output method,
        // the part to display, and the location details.
        list($locale, $timezone, $inTerritory,
        $set, $zd_year, $zd_month, $zd_day, $zd_hour, $zd_minute, $zd_second,
        $action, $part,
        $city, $useTz, $latitude, $longitude, $horizon) = $this->_getParameters();

        try {
            // We set the cache.
            $this->_setCache();

            // We verify the locale or we search the locale.
            $locale = Zend_Locale::findLocale($locale);
            // We store the locale in the registry.
            Zend_Registry::set('Zend_Locale', new Zend_Locale($locale));

            // We verify the timezone, or we search the timezone if not specified.
            $myTimezone = new Sfs_Timezone($timezone, $locale);
            $timezone = $myTimezone->findLocaleTz($inTerritory);
            // We use this timezone as the default timezone.
            date_default_timezone_set($timezone);

            if ($set) {
                // We calculate the date from now.
                $date = $this->_calcDate($set);
            } else {
                // Or we set the date as requested.
                $date = $this->_setDate($zd_year, $zd_month, $zd_day,
                $zd_hour, $zd_minute, $zd_second);
            }

            $location = new Sfs_Location;
            if ($city) {
                // We set the location according to the requested city.
                list($dateCity, $city, $latitude, $longitude) =
                $location->getDateCity($city, $timezone, $useTz, $horizon);
            } else {
                // Or we set the location according to the latitude and longitude.
                $dateCity = $location->setDateCity($latitude, $longitude, $horizon);
            }

            // We execute the action.
            $result = $this->_execAction($action, $date, $dateCity, $part);
            // We update the date and time.
            extract($date->toArray(), EXTR_PREFIX_ALL, 'zd');

        } catch (Exception $e) {
            // If we catch an exception, we return the error message.
            $result = $e->getMessage();
        }

        return array($locale, $timezone, $inTerritory,
        $set, $zd_year, $zd_month, $zd_day, $zd_hour, $zd_minute, $zd_second,
        $action, $part,
        $city, $useTz, $latitude, $longitude, $horizon,
        $result);
    }

    /* Extraction of the parameters from the GET request */
    private function _getParameters()
    {
        $locale = empty($_GET['locale'])? null : $_GET['locale'];
        $timezone = empty($_GET['timezone'])? null : $_GET['timezone'];
        $inTerritory = empty($_GET)? 1 : !empty($_GET['in-territory']);

        $set = empty($_GET)? 'now' : (isset($_GET['set'])? $_GET['set'] : '');

        $zd_year = empty($_GET['year'])? 1970 : $_GET['year'];
        $zd_month = empty($_GET['month'])? 1 : $_GET['month'];
        $zd_day = empty($_GET['day'])? 1 : $_GET['day'];
        $zd_hour = empty($_GET['hour'])? 0 : $_GET['hour'];
        $zd_minute = empty($_GET['minute'])? 0 : $_GET['minute'];
        $zd_second = empty($_GET['second'])? 0 : $_GET['second'];

        $action = isset($_GET['action'])? $_GET['action'] : null;
        $part = empty($_GET['part'])? Zend_Date::DATETIME_LONG : $_GET['part'];
        $city = empty($_GET)? ' ' : (isset($_GET['city'])? $_GET['city'] : null);
        $useTz = empty($_GET)? 1 : !empty($_GET['use-tz']);

        $latitude = empty($_GET['latitude'])? 0 : $_GET['latitude'];
        $longitude = empty($_GET['longitude'])? 0 : $_GET['longitude'];
        $horizon = isset($_GET['horizon'])? $_GET['horizon'] : null;

        return array($locale, $timezone, $inTerritory,
        $set, $zd_year, $zd_month, $zd_day, $zd_hour, $zd_minute, $zd_second,
        $action, $part,
        $city, $useTz, $latitude, $longitude, $horizon);
    }

    /* Setting the cache */
    private function _setCache()
    {
        $frontendOptions = array('lifetime' => 3600, 'automatic_serialization' => true);
        $backendOptions = array('cache_dir' => sys_get_temp_dir());
        $cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);
        Zend_Locale::setCache($cache);
    }

    /* Calculation of the date from now */
    private function _calcDate($set)
    {
        // We get the current date.
        $date = new Zend_Date();
        $set == 'now' and $set = '';

        // We extract the value to add or subtract, and the unit of the value.
        // The unit is in hours, days, months or years.
        @list($value, $unit) = explode('_', $set);

        if ($value and $unit) {
            // We add or subtract the value to the current date.
            $method = $value >= 0? 'add' : 'sub';
            $part = constant('Zend_Date::' . strtoupper($unit));
            $date->$method(abs($value), $part);
        }

        return $date;
    }

    /* Setting the date */
    private function _setDate($zd_year, $zd_month, $zd_day, $zd_hour, $zd_minute, $zd_second)
    {
        // We convert the date and time into a string.
        $dateTime = "$zd_year/$zd_month/$zd_day $zd_hour:$zd_minute:$zd_second";
        $format = 'yyyy MM dd hh mm ss';

        if (!Zend_Date::isDate($dateTime, $format)) {
            // We return an error if the date is invalid.
            throw new Exception("Bad Date/Time Format: $dateTime!");
        }

        return new Zend_Date($dateTime, $format);
    }

    /* Processing the action */
    private function _execAction($action, $date, $dateCity, $part)
    {
        switch($action) {
            case 'Zend_Date':
                $result = $date;
                break;

            case 'getSunrise':
            case 'getSunset':
                $sun = $date->$action($dateCity);
                $result = $sun->get($part);
                break;

            case 'getSunInfo':
                $result = $date->$action($dateCity);
                break;

            case 'isLeapYear':
            case 'isToday':
            case 'isTomorrow':
            case 'isYesterday':
                $result = $date->$action()? 'Yes' : 'No';
                break;

            case 'compare-now':
                $compare = $date->compare(Zend_Date::now());
                $result = $compare? ($compare > 0? 'Later' : 'Earlier') : 'Same';
                break;

            case 'compare-12':
                $compare = $date->compare(12, Zend_Date::HOUR);
                $result = $compare? ($compare > 0? 'Later' : 'Earlier') : 'Same';
                break;

            case 'equals-now':
                $result = $date->equals(Zend_Date::now())? 'Yes' : 'No';
                break;

            case 'equals-12':
                $result = $date->equals(12, Zend_Date::HOUR)? 'Yes' : 'No';
                break;

            default:
                $action = 'get';
            case 'get':
            case 'toArray':
            case 'toString':
            case 'toValue':
                $result = $date->$action($part);
                break;
        }

        return $result;
    }
}
